package main

import "fmt"

// slice 本身是没有数据的，是对array底层的一个view视图，所以它的修改是会影响原始数据的
func updateSlice(s []int) {
	s[0] = 100
}

// slice 在go中最常用 和数组类似的类型但可以很方便的进行操作
func main() {
	arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
	fmt.Println("arr[2:6]=", arr[2:6]) // 从索引的0到6获取到一个切片
	fmt.Println("arr[:6]=", arr[:6])   // 从头到第6个索引前获取
	s1 := arr[2:]
	fmt.Println("arr[2:]=", s1) // 从第2个索引获取到结尾获取
	s2 := arr[:]
	fmt.Println("arr[:]=", s2) // 从头到尾获取

	fmt.Println("after updateSlice(s1)")
	updateSlice(s1)
	fmt.Println(s1)  // 此处的索引0数据会被改变为100，因为s1是[2:]取的arr切片，相对于arr实际改的是索引2的数据
	fmt.Println(arr) // 此处的索引2数据也会被改变为100

	// slice的自动扩展
	arr[2] = 2 // 先回复arr的被修改的数据
	s1 = arr[2:6]
	s2 = s1[3:5] // s1的值是：[2 3 4 5]，此处取的是 s1[3],s1[4] ,s1[4]是不存在的，直接输出 fmt.Println(s1[4]) 会报数组越界错误
	fmt.Println("s1=", s1)
	// 此处会输出 [5,6] 原因还是因为slice是array的视图，所以通过对应关系是可以去到相对于s1不可见的6的，实现了向后扩展，
	// 扩展原则s[i]不可以超过len(s),向后扩展不可以超越底层数组的cap(s),cap就是切片开头到数组结尾的所有长度容量
	fmt.Println("s2=", s2)
	// 演示slice中的cap
	fmt.Printf("s2=%v, len(s2)=%d , cap(s2)=%d", s2, len(s2), cap(s2))

	// 向slice添加元素
	fmt.Println("add slice -----")
	s3 := append(s2, 10)
	s4 := append(s3, 11)
	s5 := append(s4, 12)
	// s4,s5 因为原arr长度不够，它们view 的不再是arr go会新加一个更长的arr来储存
	// 添加元素如果超越了cap，系统会重新分配一个更大的底层数组把原来的元素拷贝进去，原来的数组如果有在用会保留，如果没有则会被垃圾回收机制销毁
	// 由于是值传递的关系所以必须接收append的值
	fmt.Println(s3, s4, s5, arr)
}
